package com.xzq.bustack;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.Charset;
import java.util.List;

/**
 * @Author xzq
 * @Description //TODO
 * @Date 2021/11/19 14:09
 * @Version 1.0.0
 **/
public class MyDecoder extends ByteToMessageDecoder {
    //数据包基础长度
    private final int BASE_LENGITH = 4;
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> out) throws Exception {
        //基础长度不足，我们设定基础长度为4
        if (byteBuf.readableBytes() < BASE_LENGITH) {
                return;
        }
        //记录包头位置
        int beginIdx;

        while (true) {
            //获取包头开始的Index
            beginIdx = byteBuf.readerIndex();
            //标记包头开始的index
            byteBuf.markReaderIndex();
            //读到了协议的开始标志，结束while循环
            if (byteBuf.readByte() == 0x02) {
                break;
            }
            //未读到包头，略过一个字节
            //每次略过一个字节去读取，包头信息的开始标记
            byteBuf.resetReaderIndex();
            byteBuf.readByte();
            //当略过一个字节之后
            //数据包的长度，又变得不满足
            //此时,应该结束。等待后面的数据到达

            if (byteBuf.readableBytes() < BASE_LENGITH) {
                return;
            }
        }

        //剩余长度不足可读取数量{没有内容长度}
        int readableCount = byteBuf.readableBytes();
        if (readableCount <= 1) {
            byteBuf.readerIndex(beginIdx);
            return;
        }

        //长度域占4字节，读取int
        ByteBuf buf = byteBuf.readBytes(1);
        String msgLengthStr = buf.toString(Charset.forName("gbk"));
        int msgLength = Integer.parseInt(msgLengthStr);

        //剩余长度不足可读取数据[没有结尾标识]
        readableCount = byteBuf.readableBytes();
        if (readableCount < msgLength + 1) {
            byteBuf.readerIndex(beginIdx);
            return;
        }

        ByteBuf msgContent = byteBuf.readBytes(msgLength);

        //如果没有结尾标识，还原指针位置
        byte end = byteBuf.readByte();
        if (end != 0x03) {
            byteBuf.readerIndex(beginIdx);
            return;
        }

        out.add(msgContent.toString(Charset.forName("gbk")));
    }
}
